﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Business.Entities;
using GogTasks.Entities;
using System.Drawing;
using GogTasks.Logic;

namespace GogTasks.UserControls
{
    public partial class MoveUserControl : UserControl
    {
        #region Properties
        private Task _task;
        TaskForm _taskForm;
        public event EventHandler TasksChanged;
        private MobileOutlookApi _outlook;
        private  int IconMargin = 8;
        //private int IconWidth = 80;

        public event EventHandler EditClicked;


        public bool EnableEdit
        {
            set { EditButton.Enabled = value; }
            get { return EditButton.Enabled; }
        }


        public new bool Enabled
        {
            get { return base.Enabled; }
            set { 
                base.Enabled = value;
                SetEnabledPics();
            }
        }

        private static Dictionary<string, ThreeStateIcon> Icons;

        #endregion
        #region Constructors
        static MoveUserControl()
        {
            Icons = new Dictionary<string, ThreeStateIcon>();
            //AddIcon("sync");
            AddIcon("left");
            AddIcon("right");
            AddIcon("up");
            AddIcon("down");
            AddIcon("menu");
            AddIcon("edit");
            AddIcon("new");
        }

        private static void AddIcon(string iconName)
        {
            var icon = new ThreeStateIcon("pics/icons/40/" + iconName);
            icon.LoadAll();
            Icons.Add(iconName, icon);
        }

        public MoveUserControl(TaskForm taskform, MobileOutlookApi oapi)
        {
            InitializeComponent();
            _outlook = oapi;
            _taskForm = taskform;

            //SyncButton.Icon = Icons["sync"];
            LeftPic.Icon = Icons["left"];
            RightPic.Icon = Icons["right"];
            UpPic.Icon = Icons["up"];
            DownPic.Icon = Icons["down"];
            MenuButton.Icon = Icons["menu"];
            EditButton.Icon = Icons["edit"];
            MenuButton.BlinkOnClick = true; // Because it opens a context menu, mouseUp is never called
            PositionIcons();
            SetEnabledPics();
        }
        #endregion
        #region Business methods

        private void PositionIcons()
        {
            //Height = IconWidth;
            Width = Screen.PrimaryScreen.WorkingArea.Width;
            int loc = 0;

            int marginTotwidth = (Controls.Count - 1) * IconMargin;
            int iconWidth = (Width-marginTotwidth) / Controls.Count;
            if (iconWidth > 80) iconWidth = 80;
            Height = iconWidth;
            Width = Controls.Count*iconWidth + marginTotwidth;
            foreach (ImageButton button in Controls)
            {
                button.Size = new Size(iconWidth, iconWidth);
                button.Location = new Point(loc, 0);
                loc += iconWidth + IconMargin;
            }
        }

        public void UpdateEnabling()
        {
            SetEnabledPics();
        }

        //private bool enableLeft;
        //private bool enableRight;
        //private bool enableUp;
        //private bool enableDown;

        private void SetEnabledPics()
        {
            if (Enabled && _task != null)
            {
                var priorSib = _task.ParentList.GetPriorSibling(_task);
                LeftPic.Enabled = !(_task.ParentTask == null);
                RightPic.Enabled = !(priorSib == null);
                UpPic.Enabled = !(priorSib == null);
                DownPic.Enabled = !(_task.ParentList.GetNextSibling(_task) == null);
                EditButton.Icon = Icons["edit"];
            }
            else
            {
                foreach (ImageButton ctrl in this.Controls)
                {
                    if (ctrl != MenuButton && ctrl != EditButton) ctrl.Enabled = false;
                }
                EditButton.Icon = Icons["new"];
                
            }
            MenuButton.Enabled = Enabled;
        }

        public void SetMenu(MenuItem menu)
        {
            foreach (MenuItem item in menu.MenuItems)
            {
                MainMenu.MenuItems.Add(item);
            }
        }

        #endregion
        #region Event listeners
        private void LeftPic_Click(object sender, EventArgs e)
        {
            Timing.Reset();
            Timing.Time(20);
            if (!LeftPic.Enabled) return;

            var list = _task.ParentList;
            var updateList = new List<Task>();
            //Indent left 
            var siblings = list.GetSiblingsSorted(_task);
            var thisDeep = _task.GetThisAndChildren();
            foreach (Task task in thisDeep) task.IndentLevel--;
            updateList.AddRange(thisDeep);

            // Change parent
            var oldParent = _task.ParentTask;
            var newParent = _task.ParentTask.ParentTask;
            list.SetTaskParent(_task, _task.ParentTask.ParentElementId);
            
            // Take over siblings below 
            foreach (Task sibling in siblings)
            {
                if (sibling.Ordinal > _task.Ordinal) list.SetTaskParent(sibling, _task.id);
            }

            // Update
            updateList.Add(oldParent);
            updateList.Add(newParent);
            Timing.Time(21);
            OnTaskChanged(updateList, ChangeType.MoveHorizontal);
            Timing.Time(22);
            Timing.WriteToTrace();
        }

        private void RightPic_Click(object sender, EventArgs e)
        {
            if (!RightPic.Enabled) return;
            var newParent = _task.GetPriorTask();
            var oldParent = _task.ParentTask;
            _task.ParentList.SetTaskParent(_task, newParent.id);
            var thisDeep = _task.GetThisAndChildren();
            foreach (Task task in thisDeep) task.IndentLevel++;

            var updateList = new List<Task>();
            updateList.AddRange(thisDeep);
            updateList.Add(newParent);
            updateList.Add(oldParent);
            OnTaskChanged(updateList, ChangeType.MoveHorizontal);
        }

        private void UpPic_Click(object sender, EventArgs e)
        {
            if (!UpPic.Enabled) return;
            Timing.Reset();
            var priorTask = _task.GetPriorTask();
            Timing.Time(1);
            var thisDeep = _task.GetThisAndChildren();
            var priorDeep = priorTask.GetThisAndChildren();
            int diff = _task.Ordinal - priorTask.Ordinal;
            _task.AddOrdinalDeep(-diff);
            priorTask.AddOrdinalDeep(thisDeep.Count);
            thisDeep.AddRange(priorDeep);
            Timing.Time(2);
            OnTaskChanged(thisDeep, ChangeType.MoveVertical);
            Timing.Time(999);
            Timing.WriteToTrace();
        }

        private void DownPic_Click(object sender, EventArgs e)
        {
            if (!DownPic.Enabled) return;
            Task nextTask = _task.ParentList.GetNextSibling(_task);
            var thisDeep = _task.GetThisAndChildren();
            var nextDeep = nextTask.GetThisAndChildren();
            int diff = nextTask.Ordinal - _task.Ordinal;
            nextTask.AddOrdinalDeep(-diff);
            _task.AddOrdinalDeep(nextDeep.Count);
            
            thisDeep.AddRange(nextDeep);
            OnTaskChanged(thisDeep, ChangeType.MoveVertical);
        }

        internal void SetSelectedTask(Task _selectedTask)
        {
            _task = _selectedTask;
            SetEnabledPics();
        }

        private void OnTaskChanged(List<Task> tasks, ChangeType Change)
        {
            TaskList list = null;
            List<Task> changed = new List<Task>();
            foreach (Task task in tasks)
            {
                if (task != null)
                {
                    changed.Add(task);
                    _outlook.UpdateTask(task, null, true);
                    list = task.ParentList;
                }
            }
            Timing.Time(100);
            if (TasksChanged != null && list != null)
            {
                var args =  new TaskListEventArgs{
                    ChangedList = list, 
                    ChangeType = Change,
                    ChangedTasks = changed
                };
                TasksChanged.Invoke(this, args);
            }
        }

        private void EditButton_Click(object sender, EventArgs e)
        {
            if (EditClicked != null) EditClicked.Invoke(this, e);
        }

        private void MenuButton_MouseDown(object sender, MouseEventArgs e)
        {
            int sub = -400;
            if (Screen.PrimaryScreen.Bounds.Height == 320) sub = - 110;
            MainMenu.Show(MenuButton, new Point(0, sub));
        }

        #endregion

        private void NewButton_Click(object sender, EventArgs e)
        {
            if (EditClicked != null) EditClicked.Invoke(this, e);
        }


    }

    public enum ChangeType
    {
        MoveHorizontal,
        MoveVertical
    }
    public class TaskListEventArgs : EventArgs
    {
        public TaskList ChangedList {get;set;}
        public ChangeType ChangeType { get; set; }
        public List<Task> ChangedTasks { get; set; }
    }
}
